﻿using System;
using System.Collections.Generic;
using System.Reflection;
using MugenInjection.Delegates;
using MugenInjection.Infrastructure;

namespace MugenInjection.Interface.Components
{
    /// <summary>
    ///     Represents the interface that activate bindings.
    /// </summary>
    public interface IBindingActivatorComponent : IComponent
    {
        /// <summary>
        ///     Gets or sets a <see cref="IActivator" /> to inject values into properties, fields, methods in the specified object.
        /// </summary>
        IActivator ActivatorToInject { get; set; }

        /// <summary>
        /// Gets the converters.
        /// </summary>
        IList<IConverter> Converters { get; }

        /// <summary>
        /// Adds the specified <see cref="IConverter"/>.
        /// </summary>
        /// <param name="converter">The specified <see cref="IConverter"/>.</param>
        void AddConverter(IConverter converter);

        /// <summary>
        /// Removes the specified <see cref="IConverter"/>.
        /// </summary>
        /// <param name="converter">The specified <see cref="IConverter"/>.</param>
        bool RemoveConverter(IConverter converter);

        /// <summary>
        /// Gets a converter use the specified type.
        /// </summary>
        /// <typeparam name="T">The specified type.</typeparam>
        /// <returns>An instance of <see cref="IConverter"/>.</returns>
        T GetConverter<T>() where T : class, IConverter;

        /// <summary>
        ///     Activates the specified <see cref="IBinding" /> with specified <see cref="IBindingContext" />.
        /// </summary>
        /// <param name="binding">
        ///     The specified <see cref="IBinding" />.
        /// </param>
        /// <param name="bindingContext">
        ///     The specified <see cref="IBindingContext" />.
        /// </param>
        /// <returns>An instance of service.</returns>
        object Activate(IBinding binding, IBindingContext bindingContext);

        /// <summary>
        ///     Identifies the object type and create a converter for result object.
        /// </summary>
        /// <param name="context">The <see cref="IBindingContext"/> to identify.</param>
        /// <param name="originalType">The original type of service. </param>
        /// <param name="converterAction">A method to convert object(s).</param>
        /// <returns>A service type value.</returns>
        ServiceType GetServiceType(IBindingContext context, out Type originalType, out Func<object, object> converterAction);

        /// <summary>
        /// Injects values into properties, fields, methods in the specified object.
        /// </summary>
        /// <param name="target">The specified target for inject.</param>
        /// <param name="bindingContext">The specified <see cref="IBindingContext"/>.</param>
        void Inject<T>(ref T target, IBindingContext bindingContext);

        /// <summary>
        ///     Gets parameters for the specified <see cref="MethodBase" />.
        /// </summary>
        /// <param name="methodBase">
        ///     The specified <see cref="MethodBase" />.
        /// </param>
        /// <param name="bindingContext">
        ///     The specified <see cref="IBindingContext" />.
        /// </param>
        /// <returns>An instances of services.</returns>
        object[] GetParameters(MethodBase methodBase, IBindingContext bindingContext);

        /// <summary>
        ///     Gets parameter for the specified <see cref="MemberInfo" />.
        /// </summary>
        /// <param name="memberInfo">
        ///     The specified <see cref="MemberInfo" />.
        /// </param>
        /// <param name="bindingContext">
        ///     The specified <see cref="IBindingContext" />.
        /// </param>
        /// <returns>An instance of service.</returns>
        object GetParameter(MemberInfo memberInfo, IBindingContext bindingContext);
    }
}